package com.leenmvc.core.config.intercept;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.leenmvc.core.exception.BusinessException;
import com.leenmvc.core.utils.StringUtils;
import com.leenmvc.core.utils.TipUtil;
import com.leenmvc.core.utils.http.HttpContextUtils;
import com.leenmvc.core.utils.thread.ThreadLocalManager;
import com.leenmvc.core.utils.validator.ValidatorUtils;
import com.leenmvc.core.web.PageData;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 全局拦截器
 */
@Component
public class GlobalIntercept implements HandlerInterceptor {

    // 目标方法执行之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod h = (HandlerMethod) handler;
            Method controllerMethod = h.getMethod();
            if ("error".equals(controllerMethod.getName())) {
                String requestURI = request.getRequestURI();
                throw new BusinessException(TipUtil.getTip("INTERCEPT_WRONG_URL", requestURI));
            }
            RequiresPermissions annotation = controllerMethod.getAnnotation(RequiresPermissions.class);
            //存储控制器授权信息
            ThreadLocalManager.put("requiresPermissions",null == annotation ? null : annotation.value().toString());
            if (h.getMethodParameters().length > 0) {
                int index = 0;
//                String url = ThreadLocalManager.get("request_url") + "";
//                String[] pathArr = url.split("/");
//                if (BaseEntity.entityMap.get(pathArr[pathArr.length - 1]) != null) {
//                    index = 1;
//                }
                RequestBody methodAnnotation = h.getMethodParameters()[index].getParameterAnnotation(RequestBody.class);
                if (methodAnnotation != null) { // 如果是通过body的形式传递参数
                    Class<?>[] parameterTypes = controllerMethod.getParameterTypes();
                    Class<?> parameterType = parameterTypes[0];
                    String entity = null;
                    try {
                        entity = HttpContextUtils.readAsChars(request);
                    } catch (Exception ex) {
                        throw new BusinessException(TipUtil.getTip("INTERCEPT_WRONG_REQUESTBODY"));
                    }
                    Object o = null;
                    try {
                        o = JSONObject.parseObject(entity, parameterType);
                    } catch (JSONException ex) {
                        String message = ex.getMessage();
                        String matchStr = StringUtils.getMatchStr(".*(field.*)", message, 1);
                        throw new BusinessException(TipUtil.getTip("INTERCEPT_WRONG_REQUESTBODY_CONVERT", matchStr));
                    }

                    ThreadLocalManager.put("requestBody", entity);

                } else { // 通过非body的形式传递参数
                    Map<String, Object> params = HttpContextUtils.getParameterMap(request);
                    StringBuilder sb = new StringBuilder();
                    for(String key: params.keySet()) {
                        if ("page".equals(key)) {
                            Integer page = ValidatorUtils.convertToNum(TipUtil.getTip("PARAM_PAGE"), params.get(key), Integer.class);
                            if(page < 0 || page > 4294967) { // Integer.MAX_VALUE / MAX_PAGESIZE
                                throw new BusinessException(TipUtil.getTip("PARAM_PAGE"));
                            }
                        }

                        if ("pageSize".equals(key)) {
                            Integer pageSize = ValidatorUtils.convertToNum(TipUtil.getTip("PARAM_PAGESIZE"), params.get(key), Integer.class);
                            if(pageSize < 0 || pageSize > PageData.MAX_PAGESIZE) {
                                throw new BusinessException(TipUtil.getTip("PARAM_PAGESIZE"));
                            }
                        }
                        if ("_t".equals(key)) {
                            Object t = params.get("_t");
                            int length = String.valueOf(t).length();
                            if(length > 30) {
                                throw new BusinessException(TipUtil.getTip("时间戳长度过长"));
                            }
                        }

                        sb.append(key + "=" + params.get(key) + "&");
                    }
                    ThreadLocalManager.put("requestParams", sb.toString());
                }
            }
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

    }
}
